/*
 * @Author: Wanko
 * @Date: 2024-06-16 09:40:59
 * @LastEditors: Wanko
 * @LastEditTime: 2024-07-01 15:24:56
 * @Description:
 */

const Card = require('../models/card')

const { response } = require('../utils/Response')
const { CODES_NAME } = require('../utils/constant')
const { isSimilarCard } = require('../utils/card')
const dayjs = require('dayjs')
const User = require('../models/users')

class CardController {
  async find(ctx) {
    const page = parseInt(ctx.query.page) || 1
    const size = parseInt(ctx.query.size) || 50
    const skip = (page - 1) * size

    const searchKey = ctx.query.key
    let query = {
      // owner: '668225fa89138222cde956a2' // 测试
     // owner: '66812648bbebabde08542fef' // 正式testID
    }
    
    if (searchKey) {
      query = { content: { $regex: new RegExp(searchKey, 'i') } }
    }

    let cards = await Card.find(query)
      .populate('owner')
      .sort({ is_top: -1, createTime: -1 })
      .skip(skip)
      .limit(size)

    const total = searchKey ? await Card.find(query).countDocuments() : await Card.countDocuments()

     ctx.set('X-Total-Count', total)

    if (ctx.state.user) {
      console.log(ctx.state.user, '----')
      const me = await User.findById(ctx.state.user._id).select('+like_cards+collection_cards')

      const { collection_cards, like_cards } = me

      cards = cards.map((card) => ({
        ...card.toObject(),
        is_liked: like_cards.includes(card._id) ? true : false,
        is_collected: collection_cards.includes(card._id) ? true : false
      }))
    }

    response(ctx, cards)
  }

  async findById(ctx) {
    let card = await Card.findById(ctx.params.id)
    if (!card) return response(ctx, CODES_NAME.CARD_NOT_EXIST)
    
    if (ctx.state.user) {
      const me = await User.findById(ctx.state.user._id).select('+like_cards+collection_cards')
      const { collection_cards, like_cards } = me

      const is_liked = like_cards?.includes(card._id.toString()) ? true : false

      const is_collected = collection_cards?.includes(card._id.toString()) ? true : false

      card = Object.assign(card.toObject(), {
        is_liked,
        is_collected
      })
    }
    response(ctx, card)
  }

  async create(ctx) {
    const cards = await Card.find()
    const card = new Card(ctx.request.body)

    ctx.verifyParams({
      content: { type: 'string', required: true }
    })

    const isDuplicate = cards.some(({ content }) => isSimilarCard(content, card.content))

    if (isDuplicate) return response(ctx, CODES_NAME.CARD_DUPLICATE)

    const newCard = await new Card({
      ...ctx.request.body,
      owner: ctx.state.user._id
    }).save()

    response(ctx, newCard)
  }
  async update(ctx) {
    const data = ctx.request.body
    Object.assign(data, { updateTime: dayjs().format('YYYY-MM-DD HH:mm:ss') })

    const card = await Card.findByIdAndUpdate(ctx.params.id, ctx.request.body, {
      new: true
    })

    if (!card) return response(ctx, CODES_NAME.CARD_NOT_EXIST)
    response(ctx, card)
  }

  async del(ctx) {
    const card = await Card.findByIdAndDelete(ctx.params.id)
    if (!card) return response(ctx, CODES_NAME.CARD_NOT_EXIST)
    response(ctx)
  }
  // 获取随机数量卡片
  async randoms(ctx) {
    const size = parseInt(ctx.query.size) || 1
    let cards = await Card.aggregate([{ $sample: { size } }])

    if (ctx.state.user) {
      console.log(ctx.state.user, '---')
      const me = await User.findById(ctx.state.user._id).select('+like_cards+collection_cards')

      console.log(me, '------');

      const { collection_cards, like_cards } = me

      cards = cards.map((card) => ({
        ...card,
        is_liked: like_cards.includes(card._id) ? true : false,
        is_collected: collection_cards.includes(card._id) ? true : false
      }))
    }
    response(ctx, cards)
  }

  // 置顶
  async top(ctx) {
    // 将所有卡片的top属性设置为false
    await Card.updateMany({}, { is_top: false })

    // 将指定卡片的top属性设置为true
    const card = await Card.findByIdAndUpdate(ctx.params.id, { is_top: true }, { new: true })

    if (!card) return response(ctx, CODES_NAME.CARD_NOT_EXIST)
    response(ctx, card)
  }

  async unTop(ctx) {
    const card = await Card.findByIdAndUpdate(
      ctx.params.id,
      { is_top: false },
      {
        new: true
      }
    )
    if (!card) return response(ctx, CODES_NAME.CARD_NOT_EXIST)
    response(ctx, card)
  }

  // 喜欢
  async like(ctx) {
    const me = await User.findById(ctx.state.user._id).select('+like_cards')

    if (!me.like_cards.includes(ctx.params.id)) {
      me.like_cards.push(ctx.params.id)
      me.save()
      const card = await Card.findByIdAndUpdate(
        ctx.params.id,
        { $inc: { like_count: 1 } },
        {
          new: true
        }
      )
      response(ctx, card)
    } else {
      response(ctx, CODES_NAME.CARD_ALREADY_LIKED)
    }
  }

  async unLike(ctx) {
    const me = await User.findById(ctx.state.user._id).select('+like_cards')

    const index = me.like_cards.map((id) => id.toString()).indexOf(ctx.params.id)

    if (index > -1) {
      me.like_cards.splice(index, 1)
      me.save()
      const card = await Card.findByIdAndUpdate(
        ctx.params.id,
        { $inc: { like_count: -1 } },
        {
          new: true
        }
      )
      response(ctx, card)
    } else {
      response(ctx, CODES_NAME.CARD_ALREADY_LIKED)
    }
  }

  async collect(ctx) {
    const me = await User.findById(ctx.state.user._id).select('+collection_cards')

    if (!me.collection_cards.includes(ctx.params.id)) {
      me.collection_cards.push(ctx.params.id)
      me.save()
      const card = await Card.findByIdAndUpdate(
        ctx.params.id,
        { $inc: { collection_count: 1 } },
        {
          new: true
        }
      )
      response(ctx, card)
    } else {
      response(ctx, CODES_NAME.CARD_ALREADY_LIKED)
    }
  }

  async unCollect(ctx) {
    const me = await User.findById(ctx.state.user._id).select('+collection_cards')

    const index = me.collection_cards.map((id) => id.toString()).indexOf(ctx.params.id)

    if (index > -1) {
      me.collection_cards.splice(index, 1)
      me.save()
      const card = await Card.findByIdAndUpdate(
        ctx.params.id,
        { $inc: { collection_count: -1 } },
        {
          new: true
        }
      )
      response(ctx, card)
    } else {
      response(ctx, CODES_NAME.CARD_ALREADY_COLLECT)
    }
  }
}

module.exports = new CardController()
